import { Point2 } from "../point/Point2";
import { Vector2 } from "../vector/Vector2";
import { Curve2Type } from "./Curve2Type";
import { IntersectionType } from "./IntersectionType";


/**
* @description 2D 曲线基类
* @author xuld
* @date 2024-11-14
* @lastEditTime 2024-11-14 09:24:46
* @lastEditors xuld
*/
export abstract class Curve2 {
    private static _id_seed: number = 0;
    private static generateID(): number {
        return Curve2._id_seed++;
    }

    // 唯一标识
    private readonly _id: number = Curve2.generateID();

    // 曲线类型
    private _curveType: Curve2Type;

    /**
    * @description 获取唯一标识
    * @return 唯一标识
    */
    public get id(): number {
        return this._id;
    }

    constructor(curveType: Curve2Type) {
        this._curveType = curveType;
    }
    /**
    * @description 获取曲线类型
    * @return 曲线类型
    */
    public get curveType(): Curve2Type {
        return this._curveType;
    }

    /**
    * @description 转换为字符串表示
    * @returns 格式化的点字符串
    */
    public abstract toString(): string;

    /**
    * @description 获取点在线段上的参数
    * @param point - 点
    * @return 参数
    */
    public abstract getParameter(point: Point2): number;

    /**
    * @description 克隆曲线
    * @return 克隆的曲线
    */
    public abstract clone(): Curve2;

    /**
    * @description 起点
    * @return 起点
    */
    public abstract get start(): Point2;

    /**
    * @description 终点
    * @return 终点
    */
    public abstract get end(): Point2;

    /**
    * @description 长度
    * @return 长度
    */
    public abstract get length(): number;

    /**
    * @description 求曲线在参数 u 处的坐标
    * @param u - 参数方程的参数
    * @return 坐标
    */
    public abstract d0(u: number): Point2;

    /**
     * @description 求曲线在参数 u 处的坐标和切线
     * @param u - 参数方程的参数
     * @return 坐标和切线
     */
    public abstract d1(u: number): { point: Point2, tangent: Vector2 };

    /**
    * @description 点是否在线内
    * @param p - 点
    * @param epsilon - 点在线上的误差, 默认 0.00001
    * @return true 点在线上，false 点不在线上
    */
    public abstract containPoint(p: Point2, epsilon?: number): boolean;

    /**
    * @description 求点 point 到曲线的最近投影点
    * @param point - 点
    * @return 最近的投影点及其u值
    */
    public abstract projectPoint(point: Point2): { point: Point2, u: number } | undefined;

    /**
     * @description 求两条曲线的交点
     * @param curve - 另一条曲线
     * @param between - 是否在两条曲线之间，默认 false
     * @return 交点数组
     */
    public abstract getCrossPoints(curve: Curve2, between?: boolean): Array<Point2>;

    /**
     * @description 曲线细分
     * @param subdivide - 细分次数, 仅弧线时生效, 默认 30
     * @return 细分点数组
     */
    public abstract tessellate(subdivide?: number): Array<Point2>;

    /**
    * @description 线段相交性接口
    * @param curve2 - 另一条曲线
    * @param refIntersectPoints - 参考交点, 默认 []
    * @return 相交类型和交点
    */
    abstract intersect(curve2: Curve2): { type: IntersectionType, intersectPoints: Array<Point2> };

    /**
     * 获取曲线在指定参数位置的切向量
     * @param t 参数值
     * @returns 切向量
     */
    abstract tangentAt(t: number): Vector2;

    /**
     * 获取曲线在指定参数位置的曲率
     * @param t 参数值
     * @returns 曲率值
     */
    abstract curvatureAt(t: number): number;
}